﻿using System;
using System.Collections.Generic;
using System.Linq;
using CarsRegistrationService.Models;
using CarsRegistrationService.Managers.Interfaces;
using System.Transactions;
using System.Data.Objects;

namespace CarsRegistrationService.Managers
{
    public class MobileManager : BaseLinqManager, IMobileManager
    {
        private IDictionary<int, string> dbErrorMessage;
        private Request currentRequest;
        private string directoryName;
        public string DirectoryName
        {
            get { return this.directoryName; }
            set
            {
                this.directoryName = value;
                if (!System.IO.Directory.Exists(this.directoryName))
                {
                    System.IO.Directory.CreateDirectory(this.directoryName);
                }
            }
        }

        public MobileManager()
        {
            this.dbErrorMessage = new Dictionary<int, string>()
            {
                { -1, "Пользователь с таким логином уже существует" }
            };
        }

        #region IUserManager

        public bool IsUserDataCorrect(string login, string passHash)
        {
            var mobileInspector = this.GetMobileInspector(login);
            return mobileInspector != null &&
                   mobileInspector.User.PasswordHash == passHash;
        }
        public string Registration(string login, string password, string firstName,
                                   string lastName, string middleName,
                                   string passportSeries, string passportNumber)
        {
            try
            {
                if (LinqContext.Users.Any(u => u.Login == login))
                {
                    return this.dbErrorMessage[-1];
                }
                using (var ts = new TransactionScope())
                {
                    var userID = Guid.NewGuid();
                    var user = new User
                    {
                        ID = userID,
                        Login = login,
                        PasswordHash = MD5Encode(password)
                    };
                    LinqContext.Users.AddObject(user);

                    var passport = LinqContext.PersonPassports.FirstOrDefault(
                        p => p.Number == passportNumber && p.Series == passportSeries);
                    Guid passportID;
                    if (passport == null)
                    {
                        passportID = Guid.NewGuid();
                        passport = new PersonPassport
                        {
                            ID = passportID,
                            DateBirthday = DateTime.Now,
                            FirstName = firstName,
                            LastName = lastName,
                            MiddleName = middleName,
                            Number = passportNumber,
                            Series = passportSeries
                        };
                        LinqContext.PersonPassports.AddObject(passport);
                    }
                    else
                    {
                        passportID = passport.ID;
                    }

                    var inspectorID = Guid.NewGuid();
                    var inspector = new MobileInspector
                    {
                        ID = inspectorID,
                        PersonPassportID = passportID,
                        UserID = userID
                    };
                    LinqContext.MobileInspectors.AddObject(inspector);

                    LinqContext.SaveChanges();

                    ts.Complete();

                    return null;
                }
            }
            catch (Exception e)
            {
                return "Неизвестная ошибка при регистрации эксперта";
            }
        }

        #endregion IUserManager

        #region IMobileManager

        public MobileInspector GetMobileInspector(string login)
        {
            return LinqContext.MobileInspectors.FirstOrDefault(mi => mi.User.Login == login);
        }

        public Guid CreateRequest(string mobile_login, string ownerName, string vehicleNumber)
        {
            using (var ts=new TransactionScope())
            {
                var ID = Guid.NewGuid();
                var request = new Request 
                {
                    ID = ID, 
                    DateCreated = DateTime.Now,
                    MobileInspectorID = this.GetMobileInspector(mobile_login).ID,
                    OwnerName = ownerName,
                    VehicleNumber = vehicleNumber
                };
                LinqContext.AddToRequests(request);
                LinqContext.SaveChanges();
                ts.Complete();
                return ID;
            }
        }

        public string DeleteRequest(Guid ID)
        {
            var request = LinqContext.Requests.FirstOrDefault(r => r.ID == ID);
            if (request == null)
            {
                return "Данной заявки не существует";
            }

            using (var ts = new TransactionScope())
            {
                LinqContext.Requests.DeleteObject(request);
                LinqContext.SaveChanges();
                ts.Complete();
                return "OK";
            }
        }

        public void AddImageToRequest(string requestID, string imageBase64,
                                      bool first, bool last)
        {
            using (var ts = new TransactionScope())
            {
                Guid id = Guid.Parse(requestID);
                if (this.currentRequest == null || this.currentRequest.ID != id)
                {
                    this.currentRequest = LinqContext.Requests.FirstOrDefault(
                        r => r.ID == id);
                }
                
                int filesCount = LinqContext.Images.Where(i => i.RequestID == this.currentRequest.ID).Count();
                string path = this.WriteImage(requestID, imageBase64, first, filesCount);

                Image image = new Image();
                image.ID = Guid.NewGuid();
                image.FilePath = string.Format("{0}/{1}.jpg", requestID,
                                               filesCount.ToString());
                image.RequestID = this.currentRequest.ID;
                LinqContext.Images.AddObject(image);

                this.currentRequest.IsReady = last;

                LinqContext.SaveChanges();

                ts.Complete();
            }
        }

        #endregion IMobileManager

        private string WriteImage(string requestID, string imageBase64, bool first, int filesCount)
        {
            byte[] imageData = Convert.FromBase64String(imageBase64.Replace(' ', '+'));
            string requestDirectory = System.IO.Path.Combine(DirectoryName, requestID);
            if (!System.IO.Directory.Exists(requestDirectory))
            {
                System.IO.Directory.CreateDirectory(requestDirectory);
            }
            else
            {
                if (first)
                {
                    foreach (var fileName in System.IO.Directory.GetFiles(requestDirectory))
                    {
                        System.IO.File.Delete(fileName);
                    }
                }
            }
            string path = string.Format("{0}\\{1}\\{2}.jpg", DirectoryName, requestID, filesCount.ToString());
            System.IO.File.WriteAllBytes(path, imageData);

            return path;
        }
    }
}